package edu.tec.mty.core.modules.models;

import java.util.Vector;

import edu.tec.mty.core.modules.models.Position;

public class WorldModel {

	private Player[] mates = new Player[11];
	private Player[] oppts = new Player[11];
	private Vector<Player> allMates = new Vector<Player>();
	private Vector<Player> allOppts = new Vector<Player>();
	private Vector<Player> allPlayers = new Vector<Player>();
	private Vector<Player> allCurrentMates = new Vector<Player>();
	private Vector<Player> allCurrentOppts = new Vector<Player>();
	private Vector<Player> allCurrentPlayers = new Vector<Player>();
	private long gameTimestamp;
	
	public WorldModel() {
		
	}
	
	public WorldModel(Player[] mates, Player[] oppts, Vector<Player> allMates, Vector<Player> allOppts, Vector<Player> allPlayers, long gameTimestamp) {
		for (int i = 0; i < mates.length; i++) {
			this.mates[i] = new Player();//mates[i].clone();
		}
		for (int i = 0; i < oppts.length; i++) {
			this.oppts[i] = new Player();//oppts[i].clone();
		}
		for (int i = 0; i < allMates.size(); i++) {
			this.allMates.add(allMates.get(i).clone());
			if (allMates.get(i).isViewed()) {
				this.allCurrentMates.add(allMates.get(i).clone());
			}
		}
		for (int i = 0; i < allOppts.size(); i++) {
			this.allOppts.add(allOppts.get(i).clone());
			if (allOppts.get(i).isViewed()) {
				this.allCurrentOppts.add(allOppts.get(i).clone());
			}
		}
		for (int i = 0; i < allPlayers.size(); i++) {
			this.allPlayers.add(allPlayers.get(i).clone());
			if (allPlayers.get(i).isViewed()) {
				this.allCurrentPlayers.add(allPlayers.get(i).clone());
			}
		}
		this.gameTimestamp = gameTimestamp;
	}
	
	public long getGameTimestamp() {
		return this.gameTimestamp;
	}
	
	/*public Member getMateByUniformNumber(int number) throws Exception {
		if (number >= 0 && number < this.mates.length) {
			return this.mates[number];
		} else {
			throw new Exception("uniform number is out of the interval");
		}
	}
	
	public Member[] getMatesWithUniformNumber() {
		return this.mates;
	}
	
	public Member getOpponentByUniformNumber(int number) throws Exception {
		if (number >= 0 && number < this.oppts.length) {
			return this.oppts[number];
		} else {
			throw new Exception("uniform number is out of the interval");
		}
	}
	
	public Member[] getOpponentsWithUniformNumber() {
		return this.oppts;
	}*/
	
	public Player getNearestMateToPosition(Position position) throws Exception {
		if (this.allMates.size() > 0) {
			double minDistance = 0.0;
			int indexForMinDistance = -1;
			for (int i = 0; i < this.allMates.size(); i++) {
				if (this.allMates.get(i).isViewed()) {
					double distance = this.allMates.get(i).getCurrentPosition().getDistanceTo(position);
					if (i == 0) {
						minDistance = distance;
						indexForMinDistance = 0;
					} else {
						if (distance < minDistance) {
							minDistance = distance;
							indexForMinDistance = i;
						}
					}
				}
			}
			if (indexForMinDistance != -1) {
				return this.allMates.get(indexForMinDistance);
			} else {
				throw new Exception("mates vector is empty");
			}
		} else {
			throw new Exception("mates vector is empty");
		}
	}
	
	public Vector<Player> getAllMates() {
		return this.allMates;
	}
	
	/**
	 * @return all current mates on the vision range.  This method does not include player history.
	 */
	public Vector<Player> getAllCurrentMates() {
		return this.allCurrentMates;
	}
	
	public Player getNearestOpponentToPosition(Position position) throws Exception {
		if (this.allOppts.size() > 0) {
			double minDistance = 0.0;
			int indexForMinDistance = -1;
			for (int i = 0; i < this.allOppts.size(); i++) {
				if (this.allOppts.get(i).isViewed()) {
					double distance = this.allOppts.get(i).getCurrentPosition().getDistanceTo(position);
					if (i == 0) {
						minDistance = distance;
						indexForMinDistance = 0;
					} else {
						if (distance < minDistance) {
							minDistance = distance;
							indexForMinDistance = i;
						}
					}
				}
			}
			if (indexForMinDistance != -1) {
				return this.allOppts.get(indexForMinDistance);
			} else {
				throw new Exception("opponents vector is empty");
			}
		} else {
			throw new Exception("opponents vector is empty");
		}
	}
	
	public Vector<Player> getAllOpponents() {
		return this.allOppts;
	}
	
	/**
	 * @return all current opponents on the vision range.  This method does not include player history.
	 */
	public Vector<Player> getAllCurrentOpponents() {
		return this.allCurrentOppts;
	}
	
	public Player getNearestPlayerToPosition(Position position) throws Exception {
		if (this.allPlayers.size() > 0) {
			double minDistance = 0.0;
			int indexForMinDistance = -1;
			for (int i = 0; i < this.allPlayers.size(); i++) {
				if (this.allPlayers.get(i).isViewed()) {
					double distance = this.allPlayers.get(i).getCurrentPosition().getDistanceTo(position);
					if (i == 0) {
						minDistance = distance;
						indexForMinDistance = 0;
					} else {
						if (distance < minDistance) {
							minDistance = distance;
							indexForMinDistance = i;
						}
					}
				}
			}
			if (indexForMinDistance != -1) {
				return this.allPlayers.get(indexForMinDistance);
			} else {
				throw new Exception("player vector is empty");
			}
		} else {
			throw new Exception("player vector is empty");
		}
	}
	
	public Vector<Player> getAllPlayers() {
		return this.allPlayers;
	}
	
	/**
	 * @return all current players on the vision range.  This method does not include player history.
	 */
	public Vector<Player> getAllCurrentPlayers() {
		return this.allCurrentPlayers;
	}
	
}
